home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
cp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-15
|
4KB
|
211 lines
/* cp - copy files Author: Andy Tanenbaum */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define TRANSFER_UNIT 16384
char cpbuf[TRANSFER_UNIT];
int isfloppy; /* set to 1 for cp x /dev/fd? */
main(argc, argv)
int argc;
char *argv[];
{
int fd1, fd2, m, s;
struct stat sbuf, sbuf2;
if (argc < 3) usage();
/* Get the status of the last named file. See if it is a directory. */
s = stat(argv[argc - 1], &sbuf);
m = sbuf.st_mode & S_IFMT;
if (s >= 0 && m == S_IFDIR) {
/* Last argument is a directory. */
exit(cp_to_dir(argc, argv));
} else if (argc > 3) {
/* More than 2 arguments and last one is not a directory. */
usage();
} else if (s < 0 || m == S_IFREG || m == S_IFCHR || m == S_IFBLK) {
/* Exactly two arguments. Check for cp f1 f1. */
if (equal(argv[1], argv[2])) {
std_err("cp: cannot copy a file to itself\n");
exit(-1);
}
/* Command is of the form cp f1 f2. */
fd1 = open(argv[1], O_RDONLY);
if (fd1 < 0) {
stderr3("cannot open ", argv[1], "\n");
exit(1);
}
fstat(fd1, &sbuf);
m = sbuf.st_mode & S_IFMT;
if (m == S_IFDIR) {
stderr3("<", argv[1], "> directory\n");
exit(1);
}
fd2 = creat(argv[2], sbuf.st_mode & 0777);
if (fd2 < 0) {
stderr3("cannot create ", argv[2], "\n");
exit(2);
}
fstat(fd2, &sbuf2);
if ((sbuf2.st_mode & S_IFMT) == S_IFBLK) isfloppy = 1;
copyfile(fd1, fd2, argv[2]);
} else {
stderr3("cannot copy to ", argv[2], "\n");
exit(3);
}
exit(0);
}
cp_to_dir(argc, argv)
int argc;
char *argv[];
{
int i, mode, fd1, fd2, exit_status = 0;
char dirname[256], *ptr, *dp;
struct stat sbuf;
for (i = 1; i < argc - 1; i++) {
fd1 = open(argv[i], O_RDONLY);
if (fd1 < 0) {
stderr3("cannot open ", argv[i], "\n");
exit_status = 1;
continue;
}
ptr = argv[argc - 1];
dp = dirname;
while (*ptr != 0) *dp++ = *ptr++;
*dp++ = '/';
ptr = argv[i];
/* Concatenate dir and file name in dirname buffer. */
while (*ptr != 0) ptr++;/* go to end of file name */
while (ptr > argv[i] && *ptr != '/') ptr--; /* get last component */
if (*ptr == '/') ptr++;
while (*ptr != 0) *dp++ = *ptr++;
*dp++ = 0;
fstat(fd1, &sbuf);
mode = sbuf.st_mode & S_IFMT;
if (mode == S_IFDIR) {
stderr3("<", argv[i], "> directory\n");
exit_status = 1;
close(fd1);
continue;
}
fd2 = creat(dirname, sbuf.st_mode & 0777);
if (fd2 < 0) {
stderr3("cannot create ", dirname, "\n");
exit_status = 2;
close(fd1);
continue;
}
copyfile(fd1, fd2, dirname);
}
return(exit_status);
}
copyfile(fd1, fd2, name)
int fd1, fd2;
char *name;
{
int n, m, mode;
struct stat sbuf;
do {
n = read(fd1, cpbuf, TRANSFER_UNIT);
if (n < 0) {
std_err("cp: read error\n");
break;
}
if (n > 0) {
m = write(fd2, cpbuf, n);
if (m != n) {
/* Write failed. Don't keep truncated
* regular file. */
perror("cp");
fstat(fd2, &sbuf); /* check for special files */
mode = sbuf.st_mode & S_IFMT;
if (mode == S_IFREG) unlink(name);
exit(1);
}
if (isfloppy) sync(); /* purge the cache all at once */
}
} while (n == TRANSFER_UNIT);
close(fd1);
close(fd2);
}
usage()
{
std_err("Usage: cp f1 f2; or cp f1 ... fn d2\n");
exit(-1);
}
typedef char *cptr;
int equal(s1, s2)
char *s1, *s2;
{
struct stat sb1, sb2;
/* Same file, different name? */
stat(s1, &sb1);
stat(s2, &sb2);
if (memcmp((cptr) & sb1, (cptr) & sb2, sizeof(struct stat)) == 0)
return(1);
/* Same file, same name? */
while (1) {
if (*s1 == 0 && *s2 == 0) return(1);
if (*s1 != *s2) return (0);
if (*s1 == 0 || *s2 == 0) return (0);
s1++;
s2++;
}
}
int match(s1, s2, n)
char *s1, *s2;
int n;
{
while (n--) {
if (*s1++ != *s2++) return(0);
}
return(1);
}
stderr3(s1, s2, s3)
char *s1, *s2, *s3;
{
std_err("cp: ");
std_err(s1);
std_err(s2);
std_err(s3);
}
int memcmp(b1, b2, n)
cptr b1, b2;
int n;
{
while (n--) {
if (*b1 != *b2) return((int) (*b1 - *b2));
++b1;
++b2;
}
return(0);
}